package com.chen.aspect;

import com.chen.enums.ResultEnum;
import com.chen.exception.CustomException;
import com.chen.staticInfos.StaticInfo;
import com.chen.utils.JournalUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;

/**
 * 日志切面
 * Created by 陈梓平 on 2017/9/11.
 */
@Component
@Aspect
public class JournalAspect {
    /**日志输出*/
    private static final Logger logger = LoggerFactory.getLogger(JournalAspect.class);

    /**日志工具类*/
    @Autowired
    private JournalUtils aspectJournalUtils;

    /**service层切面*/
    private final String POINT_CUT = "execution(* com.chen.service..*(..))";

    @Pointcut(POINT_CUT)
    private void pointcut(){}

    /**
     * 后置最终通知（目标方法只要执行完了就会执行后置通知方法）
     * 日志管理
     * @param joinPoint
     */
    @After(value = "pointcut()")
    @Transactional
    public void doAfterAdvice(JoinPoint joinPoint) throws CustomException {
        //用的最多 通知的签名
        Signature signature = joinPoint.getSignature();
        //1.获取模块类型
        //AOP代理类的名字（包括包名）
        String declaringTypeName = signature.getDeclaringTypeName();
        logger.info("AOP代理类的名字"+declaringTypeName);
        //获取代理类的类名
        String[] split = declaringTypeName.split(StaticInfo.AOP_SPIT_CLASSNAME);
        String className = split[1];
        //获取模块名
        String[] modularTypeNames = className.split(StaticInfo.AOP_SPIT_MODULAR_TYPE);
        String modularTypeName = modularTypeNames[0];
        int modulerType = -1;
        //模块类型筛选
        modulerType = this.getModularType(modularTypeName, modulerType);

        //2.获取操作类型
        //代理的是哪一个方法
        String  methodName = signature.getName();
        logger.info("AOP代理方法的名字"+signature.getName());
        int opreationType = -1;
        opreationType = getOpreationType(joinPoint, signature, opreationType,methodName);

        if (modulerType==-1&&opreationType==-1)
            if (!StringUtils.isBlank(methodName)||!StringUtils.isBlank(modularTypeName))
                throw new CustomException(ResultEnum.JOURNAL_LOG_ERROR);

        //3.添加日志
        if (modulerType!=-1&&opreationType!=-1)
            //TODO 3.1 从请求获取用户id
            aspectJournalUtils.addJournalInfo(modulerType,opreationType, 10086);


    }
    /**
     * 模块类型筛选
     * @param modularTypeName
     * @param type
     * @return
     */
    private int getModularType(String modularTypeName, int type) {
        //模块类型筛选
        switch (modularTypeName){
            case StaticInfo.AOP_MODULAR_TYPE_FIRST:
                type = StaticInfo.MODEULARTTYPE_FIRST;
                break;
                //多模块添加
        }
        return type;
    }
    /**
     * 获取操作类型
     * @param joinPoint
     * @param signature
     * @param opreationType
     * @return
     */
    private int getOpreationType(JoinPoint joinPoint, Signature signature, int opreationType,String  methodName ) {
        switch (methodName){
            case StaticInfo.AOP_OPERATION_TYPE_ADD:
                opreationType = StaticInfo.OPERATIONTYPE_ADD;
                break;
            case StaticInfo.AOP_OPERATION_TYPE_EDIT:
                opreationType = StaticInfo.OPERATIONTYPE_UPDATE;
                break;
            case StaticInfo.AOP_OPERATION_TYPE_MOVE:
                opreationType = StaticInfo.OPERATIONTYPE_MOVER;
                break;
            case StaticInfo.AOP_OPERATION_TYPE_DELETE:
                opreationType = StaticInfo.OPERATIONTYPE_DELETE;
                break;
            case StaticInfo.AOP_OPERATION_TYPE_OPENORCLOSE:
                Object[] obj = joinPoint.getArgs();
                int arg = (int) obj[1];
                if (arg==1)
                    opreationType = StaticInfo.OPERATIONTYPE_OPEN;
                else
                    opreationType = StaticInfo.OPERATIONTYPE_CLOSE;
                break;
        }
        return opreationType;
    }
}
